﻿using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Windows;

using System.IO;
using System.IO.IsolatedStorage;

using System.Runtime.Serialization;
using System.ComponentModel;
using System.Security.Permissions;
using System.Windows.Media.Imaging;
using System.Windows.Controls;

using System.Xml.Serialization;
using slTestingStreaming.Framework;
using slTestingStreaming.Model.DTO;
using System.Runtime.Serialization.Json;
using System.Globalization;



namespace slTestingStreaming.Model.Manager
{
    public partial class TwitterManager : Bindable
    {
        public event EventHandler HasConnectedToStreaming;
        public event EventHandler HasFailedConnection;
        public event EventHandler ShowUrl;


        private StreamClient sc;
        public ObservableCollection<TweetGeo> StreamingTweets { get; set; }
        public ObservableCollection<string> StreamingTweetsQueue { get; set; }
        public ObservableCollection<Tweeter> BulkTweeters { get; set; }



        private System.Threading.Timer dtQueue;
        public bool PauseQueue { get; set; }
        public int QueueCount { get; set; }
        public bool HasSelectedTweet { get; set; }
        public int LiveStreamCount { get; set; }

        private const int Const_TimeInQueueInSeconds = 2;


        public TwitterManager()
        {
            this.PauseQueue = false;
            this.HasSelectedTweet = false;
            this.StreamingTweets = new ObservableCollection<TweetGeo>();
            this.StreamingTweetsQueue = new ObservableCollection<string>();
            this.StreamingUser = new StreamingUser();
            this.BulkTweeters = new ObservableCollection<Tweeter>();

            this.InitYedda();

            RetrieveStreamingUser();
        }

        #region Queue
        void InitQueue()
        {

            dtQueue = new System.Threading.Timer(x =>
            {
                if (!this.PauseQueue)
                {
                    if (this.StreamingTweetsQueue.Count > 0)
                    {
                        string st = this.StreamingTweetsQueue[0];

                        this.StreamingTweetsQueue.RemoveAt(0);

                        #region deserialize string to tweetgeo
                        using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(st)))
                        {
                            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(TweetGeo));
                            TweetGeo t = (TweetGeo)serializer.ReadObject(ms);

                            string[] formats = new string[] { "r", "s", "u", "yyyyMMddTHHmmss", "ddd MMM dd HH:mm:ss +0000 yyyy" };
                            DateTime dt = DateTime.ParseExact(t.created_at, formats, CultureInfo.InvariantCulture, DateTimeStyles.None);
                            //x.CreatedAtString = DateTime.UtcNow.Subtract(dt.ToUniversalTime()).Seconds.ToString();
                            t.created_at = dt.ToLocalTime().ToShortTimeString();
                            



                            Dispatcher.BeginInvoke(() =>
                            {
                                if (StreamingTweets.Count == 0)
                                {
                                    StreamingTweets.Add(t);
                                }
                                else
                                {
                                    StreamingTweets.Insert(0, t);
                                }

                                this.LiveStreamCount++;
                                this.NotifyPropertyChanged("LiveStreamCount");
                            });

                        }
                        #endregion

                    }
                }

                Dispatcher.BeginInvoke(() =>
                {
                    this.QueueCount = this.StreamingTweetsQueue.Count();
                    this.NotifyPropertyChanged("QueueCount");
                });



            }, null, TimeSpan.FromSeconds(Const_TimeInQueueInSeconds), TimeSpan.FromSeconds(Const_TimeInQueueInSeconds));


            //dtQueue.Start();
            
        }

        void dtQueue_Tick(object sender, EventArgs e)
        {

        }

        #endregion

        #region StreamingUser


        public StreamingUser StreamingUser
        {
            get { return (StreamingUser)GetValue(StreamingUserProperty); }
            set { SetValue(StreamingUserProperty, value); }
        }

        public static readonly DependencyProperty StreamingUserProperty =
            DependencyProperty.Register("StreamingUser", typeof(StreamingUser), typeof(TwitterManager), new PropertyMetadata(null));

        
        #endregion

        #region SelectedTweet


        public object SelectedTweet
        {
            get { return (object)GetValue(SelectedTweetProperty); }
            set { SetValue(SelectedTweetProperty, value); }
        }

        public static readonly DependencyProperty SelectedTweetProperty =
            DependencyProperty.Register("SelectedTweet", typeof(object), typeof(TwitterManager), new PropertyMetadata(null));

        
        #endregion


        #region SelectedTweetForPicture


        public object SelectedTweetForPicture
        {
            get { return (object)GetValue(SelectedTweetForPictureProperty); }
            set { SetValue(SelectedTweetForPictureProperty, value); }
        }

        public static readonly DependencyProperty SelectedTweetForPictureProperty =
            DependencyProperty.Register("SelectedTweetForPicture", typeof(object), typeof(TwitterManager), new PropertyMetadata(null));


        #endregion

        public void SaveStreamingUser()
        {
            try{
                IsolatedStorageSettings.ApplicationSettings["stream_user"] = this.StreamingUser.UserName;
                IsolatedStorageSettings.ApplicationSettings["stream_password"] = this.StreamingUser.Password;
                IsolatedStorageSettings.ApplicationSettings["stream_keywords"] = this.StreamingUser.Keywords;
                IsolatedStorageSettings.ApplicationSettings.Save();
            }
            catch (Exception ex) { }
        }

        public void RetrieveStreamingUser()
        {
            try
            {
                this.StreamingUser.UserName = (string)IsolatedStorageSettings.ApplicationSettings["stream_user"];
                this.StreamingUser.Password = (string)IsolatedStorageSettings.ApplicationSettings["stream_password"];
                this.StreamingUser.Keywords = (string)IsolatedStorageSettings.ApplicationSettings["stream_keywords"];


                if (this.StreamingUser.Keywords == string.Empty || this.StreamingUser.Keywords == null)
                {
                    this.StreamingUser.Keywords = "microsoft,win7,windows7,silverlight,wpf,#silverlight,#wpf,#microsoft,#windows,#win7,#azure,#sharepoint,sharepoint,#natal,#office2010,#moss,youtube,twitpic";
                }

                //this.SetValue(TwitterManager.StreamingUserProperty, this.StreamingUser);
            }
            catch (Exception ex){
                this.StreamingUser.Keywords = "microsoft,win7,windows7,silverlight,wpf,#silverlight,#wpf,#microsoft,#windows,#win7,#azure,#sharepoint,sharepoint,#natal,#office2010,#moss,youtube,twitpic";
            }

        }

        public void SaveKeywords()
        {
            try
            {
                IsolatedStorageSettings.ApplicationSettings["stream_keywords"] = this.StreamingUser.Keywords;
                IsolatedStorageSettings.ApplicationSettings.Save();
            }
            catch (Exception ex) { }

        }

        public void ReConnect()
        {
            try
            {
                StreamingTweetsQueue.Clear();
                StreamingTweets.Clear();


                if (sc != null)
                {
                    sc.Disconnect();
                    sc.NewStreamMessageEvent -= TweetRetrievedFromStream;
                    sc.HasConnected -= sc_HasConnected;
                    sc.FailedConnection -= sc_FailedConnection;
                    sc = null;
                }

                sc = StreamClient.GetStreamClient(this.StreamingUser.UserName, this.StreamingUser.Password);

                sc.NewStreamMessageEvent += new StreamClient.NewStreamMessage(TweetRetrievedFromStream);
                sc.HasConnected += new EventHandler(sc_HasConnected);
                sc.FailedConnection +=new EventHandler(sc_FailedConnection);
                sc.FollowingUIDs.Clear();
                sc.TrackingKeywords.Clear();

                //LISTEN FOR THESE KEYWORDS
                string[] keywords = this.StreamingUser.Keywords.Split(",".ToCharArray());
                foreach (string keyword in keywords)
                    sc.TrackingKeywords.Add(keyword.Trim().ToLower());

                //CREATE TWITTER LIVE CONNECTION
                sc.Connect();

            }catch(Exception ex){
                if (HasFailedConnection != null) HasFailedConnection(ex, null);
            }
            
        }

        void sc_HasConnected(object sender, EventArgs e)
        {
            if (HasConnectedToStreaming != null)
            {
                HasConnectedToStreaming(null, null);

                InitQueue();

            }


        }


        void sc_FailedConnection(object sender, EventArgs e)
        {
            if (HasFailedConnection != null) HasFailedConnection(sender, e);
        }


        public void AddBulkTweeter(Tweeter t)
        {
            var id = this.BulkTweeters.Where(x => x.id == t.id).Select(y => y.id);
            if (id != null && id.Count() == 0)
            {
                this.BulkTweeters.Add(t);
            }
        }


        void TweetRetrievedFromStream(StreamClient client, string message)
        {
            try
            {
                //using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(message)))
                //{
                //    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(TweetGeo));
                //    TweetGeo t = (TweetGeo)serializer.ReadObject(ms);

                //    Dispatcher.BeginInvoke(() =>
                //    {
                //        if (StreamingTweets.Count == 0)
                //            StreamingTweets.Add(t);
                //        else
                //            StreamingTweets.Insert(0, t);

                //        //this.NotifyPropertyChanged("StreamingUser");
                //    });

                //}

                StreamingTweetsQueue.Add(message);
            }
            catch (Exception ex)
            {

                string msg = ex.Message;
            }


        }


        public void HyperlinkClicked(Uri link)
        {
            
            //System.Windows.Browser.HtmlPage.PopupWindow(link, "_blank", null);  //this wont work in oob mode
            if (ShowUrl != null) ShowUrl(link, null);
        }
    }
}
